﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace TNPTN.Services.Abstract
{
    /// <summary>
    /// Abstract Service
    /// Author: jabraok
    /// </summary>
    /// <typeparam name="TEntity">TEntity</typeparam>
    public abstract class AbstractService<TEntity>
    {
        #region Common

        /// <summary>
        /// Context to access database
        /// </summary>
        public DB.TNPTNDataContext Context { get; set; }

        /// <summary>
        /// Constructor
        /// </summary>
        public AbstractService()
        {
            this.Context = DbServices.CreateContext();
        }

        /// <summary>
        /// Reset Context
        /// </summary>
        public void ResetContext()
        {
            this.Context = DbServices.CreateContext();
        }

        #endregion

        #region GET

        /// <summary>
        /// Get all
        /// </summary>
        /// <param name="query">Lamda expression</param>
        /// <returns>IQueryable</returns>
        public IQueryable<TEntity> Get()
        {
            return this.Context.GetTable(typeof(TEntity)).Cast<TEntity>();
        }

        /// <summary>
        /// Get By Conditons
        /// </summary>
        /// <param name="query">Lamda expression</param>
        /// <returns>IQueryable</returns>
        protected IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> query)
        {
            return this.Get().Where(query);
        }

        #endregion

        #region Insert

        /// <summary>
        /// Insert Single
        /// </summary>
        /// <param name="Entity">TEntity</param>
        public void Insert(TEntity Entity)
        {
            this.Context.GetTable(typeof(TEntity)).InsertOnSubmit(Entity);
        }

        /// <summary>
        /// Insert List
        /// </summary>
        /// <param name="Entites">list TEntity</param>
        public void Insert(List<TEntity> Entites)
        {
            this.Context.GetTable(typeof(TEntity)).InsertAllOnSubmit(Entites);
        }

        #endregion

        #region Delete

        /// <summary>
        /// Delete List
        /// </summary>
        /// <param name="Entites">list TEntity</param>
        public void Delete(List<TEntity> Entites)
        {
            this.Context.GetTable(typeof(TEntity)).DeleteAllOnSubmit(Entites);
        }

        /// <summary>
        /// Delete Single
        /// </summary>
        /// <param name="Entity">TEntity</param>
        public void Delete(TEntity Entity)
        {
            this.Context.GetTable(typeof(TEntity)).DeleteOnSubmit(Entity);
        }

        #endregion

        #region Exist

        /// <summary>
        /// check exist by conditons
        /// </summary>
        /// <param name="query">Lamda expression</param>
        /// <returns>TRUE: Exist, FLASE: not exist</returns>
        protected bool ExistBy(Expression<Func<TEntity, bool>> query)
        {
            return this.Context.GetTable(typeof(TEntity)).Cast<TEntity>().Any(query);
        }

        #endregion

        #region Count

        /// <summary>
        /// Count By Conditons
        /// </summary>
        /// <param name="query">Lamda expression</param>
        /// <returns>count by int</returns>
        protected int CountBy(Expression<Func<TEntity, bool>> query)
        {
            return this.Context.GetTable(typeof(TEntity)).Cast<TEntity>().Where(query).Count();
        }

        /// <summary>
        /// Item Count
        /// </summary>
        public int Count
        {
            get
            {
                return this.Context.GetTable(typeof(TEntity)).Cast<TEntity>().Count();
            }
        }

        #endregion
    }
}